/**
 ******************************************************************************
 * @file           : bsp_tim_capture.c
 * @brief          : Timer Input Capture Driver Implementation
 ******************************************************************************
 * @attention
 *
 * 定时器输入捕获驱动程序实现
 * 支持高级定时器（TIM1, TIM8）和通用定时器（TIM2-5）的输入捕获功能
 * 提供频率测量、占空比测量、PWM输入等功能
 *
 * 适配平台：STM32F1xx
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/TIMER/bsp_tim_capture.h"

/* ============================================================================ */
/*                          日志配置（用户可修改）                               */
/* ============================================================================ */
/* 日志后端选择：1=EasyLogger, 2=printf, 0=关闭 */
#define TIM_CAP_USE_LOG     0

#if (TIM_CAP_USE_LOG == 1)
    /* 使用EasyLogger */
    #ifndef LOG_TAG
        #define LOG_TAG    "TIM_CAP"
    #endif
    #include "elog.h"
    
#elif (TIM_CAP_USE_LOG == 2)
    /* 使用printf */
    #include <stdio.h>
    #define log_i(fmt, ...)     printf(fmt "\r\n", ##__VA_ARGS__)
    #define log_w(fmt, ...)     printf("[WARN] " fmt "\r\n", ##__VA_ARGS__)
    #define log_e(fmt, ...)     printf("[ERROR] " fmt "\r\n", ##__VA_ARGS__)
    #define log_d(fmt, ...)     printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
    
#else
    /* 关闭日志 */
    #define log_i(fmt, ...)
    #define log_w(fmt, ...)
    #define log_e(fmt, ...)
    #define log_d(fmt, ...)
#endif

/* ============================================================================ */
/*                          定时器配置（条件编译）                               */
/* ============================================================================ */

#ifdef TIM_CAP_USE_TIM1
    #define TIM_CAP_TIMx                    TIM1
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM1_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM1_CC_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM1_CC_IRQHandler
    /* TIM1通道GPIO配置（PA8-CH1, PA9-CH2, PA10-CH3, PA11-CH4） */
    #define TIM_CAP_GPIO_PORT               GPIOA
    #define TIM_CAP_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_8
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_9
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_10
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_11
    #endif
#endif

#ifdef TIM_CAP_USE_TIM2
    #define TIM_CAP_TIMx                    TIM2
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM2_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM2_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM2_IRQHandler
    /* TIM2通道GPIO配置（PA0-CH1, PA1-CH2, PA2-CH3, PA3-CH4） */
    #define TIM_CAP_GPIO_PORT               GPIOA
    #define TIM_CAP_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_0
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_1
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_2
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_3
    #endif
#endif

#ifdef TIM_CAP_USE_TIM3
    #define TIM_CAP_TIMx                    TIM3
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM3_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM3_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM3_IRQHandler
    /* TIM3通道GPIO配置（PA6-CH1, PA7-CH2, PB0-CH3, PB1-CH4） */
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PORT           GPIOA
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_6
        #define TIM_CAP_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOA_CLK_ENABLE()
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PORT           GPIOA
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_7
        #define TIM_CAP_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOA_CLK_ENABLE()
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PORT           GPIOB
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_0
        #define TIM_CAP_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE()
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PORT           GPIOB
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_1
        #define TIM_CAP_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE()
    #endif
#endif

#ifdef TIM_CAP_USE_TIM4
    #define TIM_CAP_TIMx                    TIM4
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM4_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM4_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM4_IRQHandler
    /* TIM4通道GPIO配置（PB6-CH1, PB7-CH2, PB8-CH3, PB9-CH4） */
    #define TIM_CAP_GPIO_PORT               GPIOB
    #define TIM_CAP_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOB_CLK_ENABLE()
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_6
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_7
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_8
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_9
    #endif
#endif

#ifdef TIM_CAP_USE_TIM5
    #define TIM_CAP_TIMx                    TIM5
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM5_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM5_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM5_IRQHandler
    /* TIM5通道GPIO配置（PA0-CH1, PA1-CH2, PA2-CH3, PA3-CH4） */
    #define TIM_CAP_GPIO_PORT               GPIOA
    #define TIM_CAP_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_0
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_1
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_2
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_3
    #endif
#endif

#ifdef TIM_CAP_USE_TIM8
    #define TIM_CAP_TIMx                    TIM8
    #define TIM_CAP_TIMx_CLK_ENABLE()       __HAL_RCC_TIM8_CLK_ENABLE()
    #define TIM_CAP_TIMx_IRQn               TIM8_CC_IRQn
    #define TIM_CAP_TIMx_IRQHandler         TIM8_CC_IRQHandler
    /* TIM8通道GPIO配置（PC6-CH1, PC7-CH2, PC8-CH3, PC9-CH4） */
    #define TIM_CAP_GPIO_PORT               GPIOC
    #define TIM_CAP_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()
    #if (TIM_CAP_CHANNEL == TIM_CHANNEL_1)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_6
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_2)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_7
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_3)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_8
    #elif (TIM_CAP_CHANNEL == TIM_CHANNEL_4)
        #define TIM_CAP_GPIO_PIN            GPIO_PIN_9
    #endif
#endif

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* 位域掩码定义 */
#define CAP_STATUS_FAIL         (1 << 7)    /*!< 位[7]: 捕获失败标志 */
#define CAP_STATUS_FIRST        (1 << 6)    /*!< 位[6]: 第一次捕获标志 */
#define CAP_STATUS_OVERFLOW     (0x3F)      /*!< 位[5:0]: 溢出次数掩码(0~63) */
#define CAP_OVERFLOW_MAX        63          /*!< 最大溢出次数 */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef g_tim_cap_handle = {0};                   /*!< 输入捕获定时器句柄 */

static TIM_CAP_Data_t s_cap_data = {0};                     /*!< 捕获数据 */
static uint8_t s_cap_initialized = 0;                       /*!< 初始化标志 */
static void (*s_cap_callback)(TIM_CAP_Data_t *data) = NULL; /*!< 捕获完成回调 */

/* 捕获状态变量 */
static volatile uint32_t s_cap_value1 = 0;                  /*!< 第一次捕获值 */
static volatile uint32_t s_cap_value2 = 0;                  /*!< 第二次捕获值 */

/**
 * @brief 捕获状态标志（位域定义）
 * 
 * 位域格式：0bXYZZZZZZ
 * 
 * 位[7] (X) : 捕获失败标志
 *             0 = 正常工作
 *             1 = 捕获失败（溢出次数超过63次）
 * 
 * 位[6] (Y) : 第一次捕获标志
 *             0 = 还未捕获到第一次上升沿
 *             1 = 已捕获到第一次上升沿，等待第二次
 * 
 * 位[5:0] (ZZZZZZ) : 溢出次数计数器 (0~63)
 *             记录两次上升沿之间定时器溢出的次数
 * 
 * 示例：
 * 0b00000000 = 初始状态
 * 0b01000000 = 已捕获第一次上升沿，溢出0次
 * 0b01000101 = 已捕获第一次上升沿，溢出5次
 * 0b10111111 = 捕获失败（溢出次数超限）
 */
static volatile uint8_t s_cap_status = 0;

/* Private function prototypes -----------------------------------------------*/
static void tim_cap_gpio_init(void);
static uint32_t tim_cap_get_hal_channel(void);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       输入捕获GPIO初始化
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        配置GPIO为输入捕获模式
 */
static void tim_cap_gpio_init(void)
{
    GPIO_InitTypeDef gpio_init = {0};
    
    /* 使能GPIO时钟 */
    TIM_CAP_GPIO_CLK_ENABLE();
    
    /* 配置输入捕获引脚 */
    gpio_init.Pin = TIM_CAP_GPIO_PIN;
    gpio_init.Mode = GPIO_MODE_INPUT;
    gpio_init.Pull = GPIO_PULLDOWN;  /* 下拉，避免浮空 */
    
    HAL_GPIO_Init(TIM_CAP_GPIO_PORT, &gpio_init);
}

/**
 * @brief       获取HAL库通道宏定义
 *
 * @param       无
 *
 * @retval      HAL库通道宏
 */
static uint32_t tim_cap_get_hal_channel(void)
{
    return TIM_CAP_CHANNEL;
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       输入捕获初始化
 *
 * @param[in]   arr 自动重装载值
 * @param[in]   psc 预分频器值
 *
 * @retval      无
 *
 * @note        定时器频率 = TIM_CLOCK / (psc+1)
 * @note        测量周期 = (arr+1) / 定时器频率
 */
void tim_cap_init(uint16_t arr, uint16_t psc)
{
    TIM_IC_InitTypeDef ic_config = {0};
    HAL_StatusTypeDef hal_status;
    
    if (s_cap_initialized)
    {
        log_w("TIM_CAP already initialized");
        return;
    }
    
    log_i("TIM_CAP Init: arr=%d, psc=%d", arr, psc);
    
    /* 使能定时器时钟 */
    TIM_CAP_TIMx_CLK_ENABLE();
    
    /* 配置GPIO */
    tim_cap_gpio_init();
    
    /* 配置定时器基本参数 */
    g_tim_cap_handle.Instance = TIM_CAP_TIMx;
    g_tim_cap_handle.Init.Prescaler = psc;
    g_tim_cap_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    g_tim_cap_handle.Init.Period = arr;
    g_tim_cap_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    g_tim_cap_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
    hal_status = HAL_TIM_IC_Init(&g_tim_cap_handle);
    if (hal_status != HAL_OK)
    {
        log_e("HAL_TIM_IC_Init failed: %d", hal_status);
        return;
    }
    
    /* 配置输入捕获通道 */
    ic_config.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;  /* 上升沿捕获 */
    ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI;        /* 直接映射到TI */
    ic_config.ICPrescaler = TIM_ICPSC_DIV1;                  /* 不分频 */
    ic_config.ICFilter = 0;                                  /* 无滤波 */
    
    hal_status = HAL_TIM_IC_ConfigChannel(&g_tim_cap_handle, &ic_config, tim_cap_get_hal_channel());
    if (hal_status != HAL_OK)
    {
        log_e("HAL_TIM_IC_ConfigChannel failed: %d", hal_status);
        return;
    }
    
    /* 配置中断 */
    HAL_NVIC_SetPriority(TIM_CAP_TIMx_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(TIM_CAP_TIMx_IRQn);
    
    /* 清零捕获数据 */
    s_cap_data.freq = 0;
    s_cap_data.duty = 0;
    s_cap_data.period = 0;
    s_cap_data.updated = 0;
    
    /* 清零状态标志 */
    s_cap_status = 0;
    
    s_cap_initialized = 1;
    log_i("TIM_CAP Init OK");
}

/**
 * @brief       输入捕获反初始化
 *
 * @param       无
 *
 * @retval      无
 */
void tim_cap_deinit(void)
{
    if (!s_cap_initialized)
    {
        log_w("TIM_CAP not initialized");
        return;
    }
    
    /* 停止捕获 */
    tim_cap_stop();
    
    /* 禁用中断 */
    HAL_NVIC_DisableIRQ(TIM_CAP_TIMx_IRQn);
    
    /* 反初始化定时器 */
    HAL_TIM_IC_DeInit(&g_tim_cap_handle);
    
    s_cap_initialized = 0;
    log_i("TIM_CAP DeInit OK");
}

/**
 * @brief       启动输入捕获
 *
 * @param       无
 *
 * @retval      无
 */
void tim_cap_start(void)
{
    if (!s_cap_initialized)
    {
        log_e("TIM_CAP not initialized");
        return;
    }
    
    /* 启动输入捕获和更新中断 */
    HAL_TIM_IC_Start_IT(&g_tim_cap_handle, tim_cap_get_hal_channel());
    __HAL_TIM_ENABLE_IT(&g_tim_cap_handle, TIM_IT_UPDATE);
    
    log_d("TIM_CAP started");
}

/**
 * @brief       停止输入捕获
 *
 * @param       无
 *
 * @retval      无
 */
void tim_cap_stop(void)
{
    if (!s_cap_initialized)
    {
        log_e("TIM_CAP not initialized");
        return;
    }
    
    /* 停止输入捕获和更新中断 */
    HAL_TIM_IC_Stop_IT(&g_tim_cap_handle, tim_cap_get_hal_channel());
    __HAL_TIM_DISABLE_IT(&g_tim_cap_handle, TIM_IT_UPDATE);
    
    log_d("TIM_CAP stopped");
}

/**
 * @brief       获取频率
 *
 * @param       无
 *
 * @retval      频率（Hz）
 */
uint32_t tim_cap_get_frequency(void)
{
    return s_cap_data.freq;
}

/**
 * @brief       获取占空比
 *
 * @param       无
 *
 * @retval      占空比（0-10000，表示0.00%-100.00%）
 */
uint32_t tim_cap_get_duty(void)
{
    return s_cap_data.duty;
}

/**
 * @brief       获取周期
 *
 * @param       无
 *
 * @retval      周期（定时器计数值）
 */
uint32_t tim_cap_get_period(void)
{
    return s_cap_data.period;
}

/**
 * @brief       获取完整数据
 *
 * @param[out]  data 数据指针
 *
 * @retval      无
 */
void tim_cap_get_data(TIM_CAP_Data_t *data)
{
    if (data == NULL)
    {
        log_e("data is NULL");
        return;
    }
    
    __disable_irq();
    data->freq = s_cap_data.freq;
    data->duty = s_cap_data.duty;
    data->period = s_cap_data.period;
    data->updated = s_cap_data.updated;
    s_cap_data.updated = 0;  /* 清除更新标志 */
    __enable_irq();
}

/**
 * @brief       注册捕获完成回调函数
 *
 * @param[in]   callback 回调函数指针
 *
 * @retval      无
 */
void tim_cap_register_callback(void (*callback)(TIM_CAP_Data_t *data))
{
    if (callback == NULL)
    {
        log_e("callback is NULL");
        return;
    }
    
    s_cap_callback = callback;
    log_d("Callback registered");
}

/**
 * @brief       捕获中断处理函数
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        由HAL_TIM_IC_CaptureCallback调用
 */
void tim_cap_irq_handler(void)
{
    uint32_t diff;
    uint32_t arr;
    uint32_t psc;
    uint32_t timer_freq;
    uint8_t overflow_cnt;
    
    /* 检查是否捕获失败 */
    if (s_cap_status & CAP_STATUS_FAIL)
    {
        /* 重置状态 */
        s_cap_status = 0;
        return;
    }
    
    /* 判断是第一次还是第二次捕获 */
    if (!(s_cap_status & CAP_STATUS_FIRST))
    {
        /* 第一次捕获 */
        s_cap_value1 = HAL_TIM_ReadCapturedValue(&g_tim_cap_handle, tim_cap_get_hal_channel());
        
        /* 设置第一次捕获标志，清零溢出次数 */
        s_cap_status = CAP_STATUS_FIRST;
    }
    else
    {
        /* 第二次捕获 */
        s_cap_value2 = HAL_TIM_ReadCapturedValue(&g_tim_cap_handle, tim_cap_get_hal_channel());
        
        /* 获取溢出次数 */
        overflow_cnt = s_cap_status & CAP_STATUS_OVERFLOW;
        
        /* 计算两次捕获之间的计数值 */
        if (s_cap_value2 >= s_cap_value1)
        {
            diff = s_cap_value2 - s_cap_value1;
        }
        else  /* 发生溢出 */
        {
            arr = g_tim_cap_handle.Instance->ARR;  /* 直接访问ARR寄存器 */
            diff = arr - s_cap_value1 + s_cap_value2 + 1;
        }
        
        /* 加上溢出次数 */
        arr = g_tim_cap_handle.Instance->ARR;  /* 直接访问ARR寄存器 */
        diff += overflow_cnt * (arr + 1);
        
        /* 计算频率 */
        if (diff > 0)
        {
            /* STM32F1的HAL库没有__HAL_TIM_GET_PRESCALER宏，直接访问寄存器 */
            psc = g_tim_cap_handle.Instance->PSC;
            timer_freq = TIM_CAP_TIMER_CLOCK / (psc + 1);
            s_cap_data.freq = timer_freq / diff;
            s_cap_data.period = diff;
            s_cap_data.updated = 1;
            
            /* 调用回调函数 */
            if (s_cap_callback != NULL)
            {
                s_cap_callback(&s_cap_data);
            }
        }
        
        /* 重置状态 */
        s_cap_status = 0;
    }
}

/**
 * @brief       定时器更新中断回调（溢出）
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        在捕获过程中，如果定时器溢出，计数溢出次数
 */
void tim_cap_overflow_handler(void)
{
    uint8_t overflow_cnt;
    
    /* 只有在等待第二次捕获时才计数溢出 */
    if (s_cap_status & CAP_STATUS_FIRST)
    {
        /* 获取当前溢出次数 */
        overflow_cnt = s_cap_status & CAP_STATUS_OVERFLOW;
        
        /* 溢出次数+1 */
        if (overflow_cnt < CAP_OVERFLOW_MAX)
        {
            s_cap_status = (s_cap_status & ~CAP_STATUS_OVERFLOW) | ((overflow_cnt + 1) & CAP_STATUS_OVERFLOW);
        }
        else
        {
            /* 溢出次数超限，标记失败 */
            s_cap_status |= CAP_STATUS_FAIL;
            s_cap_data.freq = 0;
            log_w("Overflow count exceeded (>%d)", CAP_OVERFLOW_MAX);
        }
    }
}
